package orm

import (
	"strings"

	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

type AtomSvrDefine struct {
	Atomsvrid        string                 `json:"atomsvrid"`
	Inputparamid     string                 `json:"inputparamid"`
	Inputparameter   map[string]interface{} `gorm:"-" json:"input-parameter"`
	Outputparamid    string                 `json:"outputparamid"`
	Outputparameter  map[string]interface{} `gorm:"-" json:"output-parameter"`
	Servicebindingid string                 `json:"-"`
	Servicebinding   Service                `gorm:"-" json:"service-binding"`
	Asdesc           string                 `json:"desc"`
	Asname           string                 `json:"name"`
	Catagoryid       string                 `json:"-"`
}

var db *gorm.DB
var err error

func init() {

	//postgres for publish
	//var dsn = "host=127.0.0.1 user=wzz password=wzz dbname=playbook port=5432 sslmode=disable TimeZone=Asia/Shanghai"
	//db, err = gorm.Open(postgres.Open(dsn), &gorm.Config{Logger: logger.Default.LogMode(logger.Info)})

	//sqlite for developer
	db, err = gorm.Open(sqlite.Open("playbook.db"), &gorm.Config{Logger: logger.Default.LogMode(logger.Info)})
}

func GetAtomSvrDefbyName(atomname string) (atomSvr AtomSvrDefine, count int64) {

	db.Table("atomsvrdefine").Where("asname = ?", atomname).Find(&atomSvr).Count(&count)

	return atomSvr, count
}

func getAtomSvrDefbyCataid(cataid string) (atomSvrLst []AtomSvrDefine, count int64) {

	db.Table("atomsvrdefine").Where("catagoryid = ?", cataid).Find(&atomSvrLst).Count(&count)
	// for i, _ := range atomSvrLst {
	// 	//获取原子服务出入参
	// 	atomSvrLst[i].Inputparameter = map[string]interface{}{"parameter": getAtomParameter(atomSvrLst[i].Inputparamid, "")}
	// 	atomSvrLst[i].Outputparameter = map[string]interface{}{"parameter": getAtomParameter(atomSvrLst[i].Outputparamid, "")}

	// 	//获取原子服务绑定
	// 	atomSvrLst[i].Servicebinding = getService(atomSvrLst[i].Servicebindingid)
	// }
	return atomSvrLst, count
}

func GetAtomSvrDef(atomSvr AtomSvrDefine) AtomSvrDefine {
	//获取原子服务出入参
	atomSvr.Inputparameter = map[string]interface{}{"parameter": getAtomParameter(atomSvr.Inputparamid, "")}
	atomSvr.Outputparameter = map[string]interface{}{"parameter": getAtomParameter(atomSvr.Outputparamid, "")}
	//获取原子服务绑定
	atomSvr.Servicebinding = getService(atomSvr.Servicebindingid)
	return atomSvr
}

func GetParamTreeByName(name string) map[string]interface{} {
	param, _ := GetParamByName(name)
	paramid := param.Parameterid
	return getAtomParameter(paramid, "")
}

func getAtomParameter(paramid string, relname string) map[string]interface{} {

	var param Parameter

	db.Table("parameter").Where("parameterid = ?", paramid).Find(&param)
	var paramMap = make(map[string]interface{})
	if relname == "" {
		paramMap["name"] = param.Name
	} else {
		paramMap["name"] = relname
	}
	paramMap["classPath"] = param.Classpath
	paramMap["optional"] = param.Optional
	paramMap["type"] = param.Type
	paramMap["paramid"] = param.Parameterid

	if param.Type == "Map" {
		if relname == "" {
			strarr := strings.Split(param.Classpath, ".")
			paramMap["mappingname"] = strarr[len(strarr)-1]
		} else {
			paramMap["mappingname"] = relname
		}

	} else if param.Type == "List" {
		paramMap["mappingname"] = paramMap["name"].(string) + "[]"
	} else {
		paramMap["mappingname"] = paramMap["name"]
	}

	var paramrel []Paramrelation
	var count int64
	db.Table("paramrelation").Where("parentparamid = ?", paramid).Find(&paramrel).Count(&count)

	if count == 0 {

		return paramMap
	}

	if param.Type == "List" {
		var paramrs []map[string]interface{}
		//list中元素为基本类型或子parameter，不允许使用javaMap(HashMap)
		pl := paramrel[0]
		//如果元素为parameter，对子参数进行递归遍历
		if len([]rune(pl.Subparamid)) == 32 {
			paramrsubs := getAtomParameter(pl.Subparamid, pl.Relname)
			paramrs = append(paramrs, paramrsubs)
			paramMap["parameter"] = paramrs
		} else {
			//如果子参数是基本类型，只需要新增一次
			var param = make(map[string]interface{})
			param["type"] = pl.Subparamid
			param["mappingname"] = pl.Subparamid
			paramrs = append(paramrs, param)
			paramMap["parameter"] = paramrs
		}

	} else if param.Type == "Map" {
		var paramrs []map[string]interface{}
		for _, pl := range paramrel {
			if pl.Reltype == "sub" {
				paramrsubs := getAtomParameter(pl.Subparamid, pl.Relname)
				paramrs = append(paramrs, paramrsubs)
			}
		}
		paramMap["parameter"] = paramrs
	}

	return paramMap
}

//以列表形式查询原子服务映射参数
func GetAtomParameterList(paramid string) []string {
	params := getAtomParameter(paramid, "")
	var mappingparams []string
	getparamapping(params, &mappingparams, "")
	return mappingparams
}

func getparamapping(params map[string]interface{}, mappingparams *[]string, temp string) {
	if params["parameter"] == nil {
		res := temp + "." + params["mappingname"].(string)
		res = string([]byte(res)[1:len([]rune(res))])
		*mappingparams = append(*mappingparams, res)
		return
	}

	for _, param := range params["parameter"].([]map[string]interface{}) {
		getparamapping(param, mappingparams, temp+"."+params["mappingname"].(string))
	}
}

func CreateAtomSvr(atomSvr *AtomSvrDefine) {
	db.Table("atomsvrdefine").Create(atomSvr)
}

func getCatagorySub(parentid string, isloop bool, catagorySub *[]interface{}, isMap bool, allCgMap map[string]interface{}, cgtype string) {
	var catagoryLst []Catagory

	db.Table("catagorydefine").Where("parentid = ?", parentid).Find(&catagoryLst)

	for i, _ := range catagoryLst {
		if isMap {
			allCgMap[catagoryLst[i].Intfname] = catagoryLst[i]
		}
		if isloop {
			catagoryLst[i].CatagorySub = make([]interface{}, 0, 40)
			getCatagorySub(catagoryLst[i].Catagoryid, isloop, &catagoryLst[i].CatagorySub, isMap, allCgMap, cgtype)
		}
		//只有cgtype为2是，才需要查询原子服务列表
		if cgtype == "2" {
			atomsvrlst, count := getAtomSvrDefbyCataid(catagoryLst[i].Catagoryid)
			if count > 0 {
				catagoryLst[i].AtomSvrLst = &atomsvrlst
			}
		}
		(*catagorySub) = append((*catagorySub), catagoryLst[i])
		//(*catagorySub)[catagoryLst[i].Intfname] = catagoryLst[i]

	}
}

func GetCgAllMap(cgtype string) map[string]interface{} {
	var allCgMap = make(map[string]interface{})
	var subCgLst = make([]interface{}, 0, 40)
	var catag Catagory

	db.Table("catagorydefine").Where("cgtype = ? and parentid = ?", cgtype, "root").Find(&catag)
	allCgMap[catag.Intfname] = catag

	getCatagorySub(catag.Catagoryid, true, &subCgLst, true, allCgMap, cgtype)

	return allCgMap
}

func GetCatagory(cgtype string, parentid string) Catagory {
	var catag Catagory
	catag.CatagorySub = make([]interface{}, 0, 40)
	if parentid == "" {
		db.Table("catagorydefine").Where("cgtype = ? and parentid = ?", cgtype, "root").Find(&catag)
		getCatagorySub(catag.Catagoryid, true, &catag.CatagorySub, false, nil, cgtype)
	} else {
		db.Table("catagorydefine").Where("catagoryid = ?", parentid).Find(&catag)
		getCatagorySub(catag.Catagoryid, false, &catag.CatagorySub, false, nil, cgtype)
	}
	//cgtype:1-编排服务、2-原子服务、4-子流程
	if cgtype == "1" {
		processLst, count := getProcessbyCataid(catag.Catagoryid, false)
		if count > 0 {
			catag.ProcessLst = &processLst
		}
	} else if cgtype == "2" {
		atomsvrlst, count := getAtomSvrDefbyCataid(catag.Catagoryid)
		if count > 0 {
			catag.AtomSvrLst = &atomsvrlst
		}
	} else if cgtype == "4" {
		processLst, count := getProcessbyCataid(catag.Catagoryid, true)
		if count > 0 {
			catag.ProcessLst = &processLst
		}
	}
	return catag
}

func GetParamForCrtBean(parameterid string, tableType string) (param *Parameter, subparamLst *[]Parameter, paramrelst *[]Paramrelation) {

	var paramdef Parameter
	var subparamrelLstDef []Paramrelation
	var count int64
	var subparamLstDef []Parameter
	if tableType == "0" {
		db.Table("parameter").Where("parameterid = ?", parameterid).Find(&paramdef)
	} else if tableType == "1" {
		db.Table("paramdefine").Where("parameterid = ?", parameterid).Find(&paramdef)
	}
	// db.Table("parameter").Where("parameterid = ?", parameterid).Find(&paramdef)
	if paramdef.Type == "Map" && strings.Contains(paramdef.Classpath, ".") {
		subparamrelLstDef, count = GetParameterbyId(parameterid, "")

		var subparmlst []string
		for _, subparmrel := range subparamrelLstDef {
			subparmlst = append(subparmlst, subparmrel.Subparamid)
		}

		if count > 0 {
			if tableType == "0" {
				db.Table("parameter").Where("parameterid in  (?)", subparmlst).Find(&subparamLstDef)
			} else if tableType == "1" {
				db.Table("paramdefine").Where("parameterid in  (?)", subparmlst).Find(&subparamLstDef)
			}
			//db.Table("parameter").Where("parameterid in  (?)", subparmlst).Find(&subparamLstDef)
		}
	}
	param = &paramdef
	paramrelst = &subparamrelLstDef
	subparamLst = &subparamLstDef

	return param, subparamLst, paramrelst
}

func GetParamByName(name string) (param Parameter, count int64) {

	db.Table("parameter").Where("name = ?", name).Find(&param).Count(&count)
	return param, count
}

func GetParameterbyId(parentparamid string, subparamid string) (paramrelst []Paramrelation, count int64) {
	if subparamid == "" {
		db.Table("paramrelation").Where("parentparamid = ?", parentparamid).Find(&paramrelst).Count(&count)
	} else {
		db.Table("paramrelation").Where("parentparamid = ? and subparamid = ?", parentparamid, subparamid).Find(&paramrelst).Count(&count)
	}

	return paramrelst, count
}

func GetAllActivity() []Activity {
	var acti []Activity

	db.Table("activity").Find(&acti)

	for i, _ := range acti {
		//获取原子服务出入参
		acti[i].Inputparameter = map[string]interface{}{"parameter": getParameter(acti[i].Inputparamid, "")}
		acti[i].Outputparameter = map[string]interface{}{"parameter": getParameter(acti[i].Outputparamid, "")}

		//获取原子服务绑定
		acti[i].Servicebinding = getService(acti[i].Servicebindingid)

		// acti[i].Inputparammapping = map[string][]Mapping{"massage-bean-mapping": []Mapping{}}
		// acti[i].Outputparammapping = map[string][]Mapping{"massage-bean-mapping": []Mapping{}}

	}

	return acti
}
